/*-
 * Copyright (c) 2006 - 2009 CTPP Team
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *	notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *	notice, this list of conditions and the following disclaimer in the
 *	documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the CTPP Team nor the names of its contributors
 *	may be used to endorse or promote products derived from this software
 *	without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	  ctpp2.hpp
 *
 * $CTPP$
 */

#ifndef __CTPP2_HPP__
#define __CTPP2_HPP__ 1

#ifdef _MSC_VER
#include "windows.h"
#undef WIN32
#define WIN32 1
#endif
#include "pycxx.hpp"
#include <CTPP2Types.h>

#include <map>

namespace CTPP
{

class Bytecode;
class SyscallHandler;
class SyscallFactory;
class CDT;
class VM;
class VMExecutable;
class VMMemoryCore;

//
// CTPP2 main object
//
class CTPP2: public Py::PythonExtension<CTPP2>
{
public:
	CTPP2(const UINT_32 & argStackSize,
	      const UINT_32 & codeStackSize,
	      const UINT_32 & stepsLimit,
	      const UINT_32 & maxFunctions);

	virtual ~CTPP2() throw();

	static void InitType();

	// Emit parameters
	Py::Object Param(const Py::Tuple & args);

	// Reset parameters
	Py::Object Reset(const Py::Tuple & args);

	// Emit JSON parameters
	Py::Object JSONParam(const Py::Tuple & args);

	// Get output
	Py::Object Output(const Py::Tuple & args);

	// Include directories
	Py::Object IncludeDirs(const Py::Tuple & args);

	// Load bytecode
	Py::Object LoadBytecode(const Py::Tuple & args);

	// Parse template
	Py::Object ParseTemplate(const Py::Tuple & args);

	// Dump parameters
	Py::Object DumpParams(const Py::Tuple & args);

	// Load user defined function
	Py::Object LoadUDF(const Py::Tuple & args);

	// Get hash with last error description
	Py::Object GetLastError(const Py::Tuple & args);

private:
	typedef CTPP::SyscallHandler * ((*InitPtr)());

	// Standard library factory
	CTPP::SyscallFactory               * syscallFactory;
	// CDT Object
	CTPP::CDT                          * cdt;
	// Virtual machine
	CTPP::VM                           * vm;

	struct HandlerRefsSort:
	  public std::binary_function<std::string, std::string, bool>
	{
		/**
		  @brief comparison operator
		  @param x - first argument
		  @param y - first argument
		  @return true if x > y
		*/
		inline bool operator()(const std::string &x,
		                       const std::string &y) const
		{
			return (strcasecmp(x.c_str(), y.c_str()) > 0);
		}
	};

	// Loadable user-defined function
	struct LoadableUDF
	{
		// Function file name
		std::string             filename;
		// Function name
		std::string             udf_name;
		// Function instance
		CTPP::SyscallHandler  * udf;
	};

	typedef std::map<std::string, LoadableUDF, HandlerRefsSort> ExtraFnMap;
	ExtraFnMap extraFn;
	std::vector<std::string> includeDirs;
};


//
// Bytecode object
//
class Bytecode: public Py::PythonExtension<Bytecode>
{
public:
	// Create bytecode object
	Bytecode(CCHAR_P filename, INT_32 iFlag,
	         const std::vector<std::string> & includeDirs);

	static void InitType();

	// Save bytecode
	Py::Object Save(const Py::Tuple & args);

	// Get core
	Py::Object GetCore(const Py::Tuple & args);

	// Destructor
	virtual ~Bytecode() throw();

private:
	// Default constructor
	Bytecode();
	// Copy constructor
	Bytecode(const Bytecode & oRhs);
	// Operator =
	Bytecode & operator=(const Bytecode & oRhs);

	// Memory core
	CTPP::VMExecutable   * core;
	// Memory core size
	UINT_32                coreSize;
	// Ready-to-run program
	CTPP::VMMemoryCore   * vmMemCore;
};


//
// CTPP2 module object
//
class CTPP2Module : public Py::ExtensionModule<CTPP2Module>
{
public:
	CTPP2Module();

	virtual ~CTPP2Module() throw() { ;; }

private:
	Py::Object CreateCTPP2(const Py::Tuple & args);
};

} // namespace CTPP

#endif // __CTPP2_HPP__

